﻿using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;

namespace Toybox.Logger
{
	/// <summary>
	/// Trace用Logクラス
	/// </summary>
	public static class TraceLogger
	{
		private const string TRACE_LOG_FILE = "TRACE_LOG_FILE";

		private static TraceListener listener;

		/// <summary>
		/// Log書き出し
		/// </summary>
		/// <param name="text"></param>
		public static void WriteLine(string text)
		{
			StackFrame sf1 = new StackFrame(1);

			Trace.WriteLine(
				DateTime.Now.ToString() + " : "
				+ sf1.GetMethod().ReflectedType.Name + " - "
				+ sf1.GetMethod().Name + " : "
				+ text);
		}

		/// <summary>
		/// Logの有効無効
		/// </summary>
		public static bool Enable
		{
			get { return listener != null && Trace.Listeners.Contains(listener); }
			set
			{
				if (value == _enable) return;

				if (value)
				{
					try
					{
						// File Path 生成
						string path = LoggerHelper.GetExeDirectory();
						if (string.IsNullOrEmpty(path)) return;

						path = Path.Combine(path, "log");
						if (!Directory.Exists(path)) Directory.CreateDirectory(path);

						string fileName = "trace_" + DateTime.Now.ToString("yyyyMMdd") + ".log";
						path = Path.Combine(path, fileName);

						LoggerHelper logger = new LoggerHelper();
						logger.FilePath = path;
						logger.TraceListenerName = TRACE_LOG_FILE;
						logger.AutoFlush = true;

						listener = logger.CreateTraceListener();
						Trace.Listeners.Add(listener);

						// ログ開始
						Trace.WriteLine(DateTime.Now.ToString() + " : " + "TraceLogger start.");

						_enable = value;
					}
					catch (Exception ex)
					{
						Debug.WriteLine(DateTime.Now.ToString() + " : " + ex.Message);
					}
				}
				else
				{
					Trace.Listeners.Remove(listener);
					listener = null;

					_enable = value;
				}
			}
		}
		private static bool _enable = false;
	}

	/// <summary>
	/// Debug用Logクラス
	/// </summary>
	public static class DebugLogger
	{
		private const string DEBUG_LOG_FILE = "DEBUG_LOG_FILE";

		private static TraceListener listener;

		/// <summary>
		/// Log書き出し
		/// </summary>
		/// <param name="text"></param>
		public static void WriteLine(string text)
		{
			StackFrame sf1 = new StackFrame(1);

			Debug.WriteLine(
				DateTime.Now.ToString() + " : "
				+ sf1.GetMethod().ReflectedType.Name + " - "
				+ sf1.GetMethod().Name + " : "
				+ text);
		}

		/// <summary>
		/// Logの有効無効
		/// </summary>
		public static bool Enable
		{
			get { return listener != null && Debug.Listeners.Contains(listener); }
			set
			{
				if (value == _enable) return;

				if (value)
				{
					try
					{
						// File Path 生成
						string path = LoggerHelper.GetExeDirectory();
						if (string.IsNullOrEmpty(path)) return;

						path = Path.Combine(path, "log");
						if (!Directory.Exists(path)) Directory.CreateDirectory(path);

						string fileName = "debug_" + DateTime.Now.ToString("yyyyMMdd") + ".log";
						path = Path.Combine(path, fileName);

						LoggerHelper logger = new LoggerHelper();
						logger.FilePath = path;
						logger.TraceListenerName = DEBUG_LOG_FILE;
						logger.AutoFlush = true;

						listener = logger.CreateTraceListener();
						Debug.Listeners.Add(listener);

						// ログ開始
						Debug.WriteLine(DateTime.Now.ToString() + " : " + "DebugLogger start.");

						_enable = value;
					}
					catch (Exception ex)
					{
						Debug.WriteLine(DateTime.Now.ToString() + " : " + ex.Message);
					}
				}
				else
				{
					Debug.Listeners.Remove(listener);
					listener = null;

					_enable = value;
				}
			}
		}
		private static bool _enable = false;
	}

	/// <summary>
	/// LoggerHelper クラス
	/// </summary>
	public class LoggerHelper
	{

		#region [Static]

		/// <summary>
		/// 実行ファイルのディレクトリ取得
		/// </summary>
		/// <returns></returns>
		public static string GetExeDirectory()
		{
			try
			{
				FileInfo fi = new FileInfo(Assembly.GetEntryAssembly().Location);
				return fi.Directory.FullName;
			}
			catch { return null; }
		}

		#endregion [Static]


		#region Public Members

		/// <summary>
		/// File Path
		/// </summary>
		public string FilePath { get; set; }
		
		/// <summary>
		/// TraceListener Name
		/// </summary>
		public string TraceListenerName { get; set; }

		/// <summary>
		/// 自動でログを書き出すか
		/// </summary>
		public bool AutoFlush { get; set; }

		#endregion Public Members


		#region Public Methods

		/// <summary>
		/// TraceListenerを作成する
		/// </summary>
		/// <returns></returns>
		public TraceListener CreateTraceListener()
		{
			if (string.IsNullOrEmpty(this.FilePath))
				throw new ArgumentNullException("FilePath");

			if (string.IsNullOrEmpty(this.TraceListenerName))
				throw new ArgumentNullException("TraceListenerName");

			StreamWriter sw = new StreamWriter(this.FilePath, true);
			sw.AutoFlush = this.AutoFlush;

			TextWriter tw = TextWriter.Synchronized(sw);

			return new TextWriterTraceListener(tw, this.TraceListenerName);
		}

		#endregion Public Methods

	}
}
